package net.myspring.middle.security;

import net.myspring.common.utils.Collections3;
import net.myspring.middle.domain.Account;
import net.myspring.middle.mapper.AccountMapper;
import net.myspring.middle.mapper.PermissionMapper;
import net.myspring.middle.mapper.RoleMapper;
import net.myspring.middle.service.MenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * Created by liuj on 2016-07-25.
 */

@Service("customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private MenuService menuService;


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Account account = accountMapper.findByLoginName(username);
        if (account == null) {
            throw new UsernameNotFoundException("Username " + username + " is not found");
        } else {
            account.setMenus(menuService.findMenuByAccount(account.getId()));
            boolean enabled = true;
            boolean accountNonExpired = true;
            boolean credentialsNonExpired = true;
            boolean accountNonLocked = true;
            UserDetails userDetails = new CustomUserDetails(
                    account.getLoginName(),
                    account.getPassword(),
                    enabled,
                    accountNonExpired,
                    credentialsNonExpired,
                    accountNonLocked,
                    getAuthorities(account),
                    account);
            return userDetails;
        }
    }

    /**
     * Retrieves a collection of {@link GrantedAuthority} based on a list of
     * roles
     *
     * @param account the assigned roles of the account
     * @return a collection of {@link GrantedAuthority}
     */
    private Collection<? extends GrantedAuthority> getAuthorities(Account account) {
        Set<SimpleGrantedAuthority> authList = new TreeSet<SimpleGrantedAuthority>(new SimpleGrantedAuthorityComparator());
        List<String> roleCodes = roleMapper.findCodeByAccountId(account.getId());
        List<String> permissionCodes = permissionMapper.findCodeByAccountId(account.getId());
        if (Collections3.isNotEmpty(roleCodes)) {
            for (String roleCode : roleCodes) {
                authList.add(new SimpleGrantedAuthority("ROLE" + roleCode));
            }
        }
        if (Collections3.isNotEmpty(permissionCodes)) {
            for (String permissionCode : permissionCodes) {
                authList.add(new SimpleGrantedAuthority("PERM_" + permissionCode));
            }
        }
        return authList;
    }


    private static class SimpleGrantedAuthorityComparator implements Comparator<SimpleGrantedAuthority> {
        @Override
        public int compare(SimpleGrantedAuthority o1, SimpleGrantedAuthority o2) {
            return o1.equals(o2) ? 0 : -1;
        }
    }

}
